namespace Domotica.Windows.Controls
{
    using Domotica.Windows.Input;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Speech.Recognition;
    using System.Windows.Automation.Peers;
    using System.Windows.Documents;
    using System.Windows.Input;

    public class SpeechExtender : AdornerDecorator
    {
        private bool _InitSpeechRecognitionDone;
        private SpeechRecognizer recognizer;

        public event SpeechEventHandler SpeechEvent;

        public SpeechExtender()
        {
            this._InitSpeechRecognitionDone = false;
        }

        private bool DoRaiseCommand(string choiceText)
        {
            if (string.IsNullOrEmpty(choiceText))
            {
                return false;
            }
            SpeechEventArgs sea = new SpeechEventArgs(SpeechDevice.Current, 0, choiceText);
            sea.RoutedEvent = SpeechDevice.SpeechEvent;
            typeof(CommandManager).InvokeMember("TranslateInput", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Static, null, typeof(CommandManager), new object[] { this, sea });
            if (!sea.Handled)
            {
                this.DoSpeechEvent(sea);
            }
            if (AutomationPeer.ListenerExists(AutomationEvents.InvokePatternOnInvoked))
            {
                AutomationPeer peer = UIElementAutomationPeer.CreatePeerForElement(this);
                if (peer != null)
                {
                    peer.RaiseAutomationEvent(AutomationEvents.InvokePatternOnInvoked);
                }
            }
            return sea.Handled;
        }

        private void DoSpeechEvent(SpeechEventArgs e)
        {
            SpeechEventHandler handler = this.SpeechEvent;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        public override void EndInit()
        {
            base.EndInit();
            this.InitSpeechRecognition();
        }

        private void InitSpeechRecognition()
        {
            if (!this._InitSpeechRecognitionDone)
            {
                bool choicesAdded = false;
                Choices choices = new Choices();
                foreach (InputBinding b in InputBindings)
                {
                    if (b is SpeechBinding)
                    {
                        SpeechBinding sb = (SpeechBinding)b;
                        choices.Add(sb.ChoiceText);
                        choicesAdded = true;
                    }
                   
                }
                if (choicesAdded)
                {
                    try
                    {
                        GrammarBuilder grammarBuilder = new GrammarBuilder(choices);
                        Grammar grammar = new Grammar(grammarBuilder);
                        this.recognizer = new SpeechRecognizer();
                        this.recognizer.LoadGrammar(grammar);
                        this.recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(this.SpeechRecognized);
                    }
                    catch(Exception e)
                    {}
                }
            }
        }

        private void SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            this.DoRaiseCommand(e.Result.Text);
        }
    }
}

